import { NAME, Picture, Setting } from "./data";

// loading animation
const svgLoading = `<div class="loading-wrap ${NAME.CSS_ITEM}" style="width:60px;height:60px;"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="60px" height="60px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50" xml:space="preserve">
                <path fill="#7558da" d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" transform="rotate(275.098 25 25)">
                    <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"></animateTransform>
                </path>
            </svg></div>`;

const defaultSetting = {
    width: '100%',
    height: '100%',
    gutter: '20px',
    lazyLoad: 1,        // 除了当前的图片，还加载后面几张图片，数值大于等于0
}

/*
box model
<container>                             // user's layer
    <div.pz-pics>                       // ui root
        <div.pz-control>                // touching element
            <div.pz-pic>                // image wrapper
                <img>                   // image
            <div.pz-pic>
                <div.loading-wrap>      // loading element
                    <svg>
            <div.pz-pic>
            ...
*/
const render = {
    container: document.body,
    pics: [] as Picture[],
    setting: Object.assign({}, defaultSetting),
    // size: [] as string[],
    // sizeWrap: [] as string[],
    sizeImage: [] as string[],
    initEngineSize: () => { },

    render(el: HTMLElement, setting: Setting, cb: (elWrap: HTMLDivElement) => typeof render.initEngine) {
        render.setting = Object.assign({}, defaultSetting, setting);
        render.pics = setting.images;
        el.innerHTML = render.htmlPics(render.pics);
        render.container = el;

        render.resize();
        render.initEngineSize = cb(render.getItemPicWrapper());
        
        el.addEventListener('resize', render.resizeDomEvent);
        window.addEventListener('resize', render.resizeDomEvent);
    },
    htmlPics(pics: Picture[]) {
        let html = pics.map((pic, index) => render.htmlPic(pic, index)).join("");
        html = `<div class="${NAME.CSS_PICS}">
            <div class="${NAME.CSS_CONTROL}">${html}</div></div>`;
        return html;
    },
    htmlPic(pic: Picture, index: number) {
        return `<div class="${NAME.CSS_PIC}" img_src="${pic}">${svgLoading}</div>`;
    },
    loadImg(elImageWrap: HTMLElement) {
        const img = document.createElement('img');
        const url = elImageWrap.getAttribute('img_src');
        img.src = url;
        img.style.display = 'none';
        document.body.appendChild(img);
        img.onload = (e) => {
            elImageWrap.innerHTML = '';
            elImageWrap.appendChild(img);
            img.style.display = '';
            render.resetItemSize(elImageWrap);
        };
    },

    getItemPicWrapper(): HTMLElement {
        return document.querySelector(`.${NAME.CSS_PICS}`);
    },
    getItemPicCtrl(): HTMLElement {
        return render.container.querySelector(`.${NAME.CSS_CONTROL}`);
    },
    getItemPic(): HTMLElement {
        return render.container.querySelectorAll(`.${NAME.CSS_PIC}`);
    },
    getItemElement(parent: HTMLElement): HTMLElement {
        return parent.querySelector(`.${NAME.CSS_ITEM}`);
    },
    resizeDomEventTimeout: 0,
    resizeDomEvent() {
        window.clearTimeout(render.resizeDomEventTimeout);
        render.resizeDomEventTimeout = window.setTimeout(render.resizeDomEventHandler, 200);
    },
    resizeDomEventHandler() {
        render.resize();
    },
    resize() {
        const setting = render.setting;
        const elWrap = render.getItemPicWrapper();
        const sizeWrap = [];        // div.pz-pics
        const sizeImage = render.sizeImage;       // img.pz-item
        // const size = render.size;

        const sizeContainer = [parseFloat(render.container.clientWidth), parseFloat(render.container.clientHeight)];

        // Set fixed size for the wrapper.
        sizeContainer.forEach((s, i) => {
            const item = setting.sizeWrap[i];
            sizeWrap[i] = item.endsWith('%') ? s * parseFloat(item) / 100 + 'px' : item;
        });
        elWrap.style.width = sizeWrap[0];
        elWrap.style.height = sizeWrap[1];

        // Set fixed size for all images.
        sizeContainer[2] = sizeContainer[0];
        sizeContainer.forEach((s, i) => {
            const item = setting.sizeImage[i];
            sizeImage[i] = item.endsWith('%') ? s * parseFloat(item) / 100 + 'px' : item;
        });
        const elImageWrap = render.getItemPic();
        for (let index = 0; index < elImageWrap.length; index++) {
            elImageWrap[index].style.paddingRight = sizeImage[2];
        }

        // size[0] = setting.width.endsWith('%') ? sizeContainer[0] * parseFloat(setting.width) / 100 + 'px' : setting.width;
        // size[1] = setting.height.endsWith('%') ? sizeContainer[1] * parseFloat(setting.height) / 100 + 'px' : setting.height;
        // size[2] = setting.gutter.endsWith('%') ? sizeContainer[0] * parseFloat(setting.gutter) / 100 + 'px' : setting.gutter;
        // size[3] = (parseFloat(size[0]) + parseFloat(size[2])) * render.pics.length + 'px';


        const paddingLeft = (parseFloat(sizeWrap[0]) - parseFloat(sizeImage[0])) / 2;
        const widthCtrl = (parseFloat(sizeImage[0]) + parseFloat(sizeImage[2])) * render.pics.length
            + paddingLeft;
        const elCtrl = render.getItemPicCtrl();
        elCtrl.style.width = widthCtrl + 'px';
        elCtrl.style.paddingLeft = paddingLeft + 'px';

        render.resetItemSize(null);
        // callback for engine to resize frame
        render.initEngineSize();
    },
    /**
     * resize image wrapper
     * @param imageWrap 
     */
    resetItemSize(imageWrap: HTMLElement | null) {
        // const elWrap = this.getItemPicWrapper();
        // const size = [elWrap.clientWidth, elWrap.clientHeight];
        const size = render.sizeImage;
        if (imageWrap) {
            imageWrap.style.width = size[0];
            imageWrap.style.height = size[1];
        } else {
            const elItems = render.getItemPic();
            for (let index = 0; index < elItems.length; index++) {
                imageWrap = elItems[index] as HTMLElement;
                imageWrap.style.width = size[0];
                imageWrap.style.height = size[1];
            }
        }
    },
    // resetCenterPosition(elImageWrap: HTMLElement) {
    //     const elItem = render.getItemElement(elImageWrap);
    //     const size = [elItem.clientWidth, elItem.clientHeight];
    //     const wrapSize = [elImageWrap.clientWidth, elImageWrap.clientHeight];
    //     const translate = [
    //         (wrapSize[0] - size[0]) / 2,
    //         (wrapSize[1] - size[1]) / 2,
    //     ];
    //     elImageWrap.style.transform = `translate(${translate[0]}px, ${translate[1]}px)`;
    // },
    /**
     * callback while page has jumped
     * @param page 
     */
    listenerJumpPage(page: number) {
        const elImageWrap = render.getItemPic();
        const count = render.setting.lazyLoad;
        for (let index = page - 1;
            index < elImageWrap.length && index <= page - 1 + count;
            index++) {
            const element = elImageWrap[index];
            const img = element.querySelector('img');
            if (!img) {
                render.loadImg(element);
            }
        }
    },
};

export default render;